﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

using System.Text.RegularExpressions;
using System.IO;

namespace Quadarax.Foundation.IO
{
    public class QIndexedFile : System.Collections.IEnumerable
    {        
        private FileStream m_oFS;
        private StreamReader m_oSR;
        private List<long> m_oBookmarks = new List<long>();
        
        private QIndexedFile()
        {
            //no default constructor. This means filename and pattern are required.
        }

        ~QIndexedFile()
        {
            Close();
        }

        /// 
        /// opens a file and parses it for the pattern string. Constructs a list of locations where the string is located.
        /// 
        /// 
        /// string to mark indexs for.
        public QIndexedFile(string sFileName, string sSearchPattern)
        {
            Init(sFileName);
            ScanFile(sSearchPattern);
        }
        /// 
        /// Opens a file and parses it using the supplied regular expression. Constructs a list of locations where the string is located.
        /// 
        /// 
        /// 
        public QIndexedFile(string sFileName, Regex oSearchPattern)
        {
            Init(sFileName);
            ScanFile(oSearchPattern);
        }        
        
        public int Count
        {
            get { return m_oBookmarks.Count; }
        }

        public long this[int nIndex]
        {
            get { return m_oBookmarks[nIndex]; }
        }
        
        public void Close()
        {
            m_oSR.Close();
            m_oFS.Close();
        }
        
        private void Init(string sFileName)
        {
            m_oFS = new FileStream(sFileName, FileMode.Open);
            m_oSR = new StreamReader(m_oFS);
        }        


        private void ScanFile(string sSearchPattern)
        {
            string s = Regex.Escape(sSearchPattern);
            Regex oRe = new Regex(s);
            ScanFile(oRe);
        }

        private void ScanFile(Regex oSearchPattern)
        {
            long nPos = 0;
            string sLine = string.Empty;
            while (m_oSR.Peek() != -1)
            {
                sLine = m_oSR.ReadLine();
                MatchCollection oMatches = oSearchPattern.Matches(sLine);
                foreach (Match oMatch in oMatches)
                {
                    if (oMatch.Success)
                    {
                        m_oBookmarks.Add(oMatch.Index + nPos);
                    }
                }
                nPos = nPos + sLine.Length + 2; // add two for the CR/LF readline strips.
            }
            Close();
        }

        #region IEnumerable Members

        public System.Collections.IEnumerator GetEnumerator()
        {
            return new QIndexedFileEnumerator(this);
        }

        #endregion
    }
}
